package com.shuzhi.stationarysource.modules.quartz.utils;

import com.shuzhi.stationarysource.config.thread.ThreadPoolExecutorUtil;
import com.shuzhi.stationarysource.modules.quartz.domain.QuartzJob;
import com.shuzhi.stationarysource.modules.quartz.domain.QuartzLog;
import com.shuzhi.stationarysource.modules.quartz.repository.QuartzLogRepository;
import com.shuzhi.stationarysource.modules.quartz.service.QuartzJobService;
import com.shuzhi.stationarysource.utils.SpringContextHolder;
import com.shuzhi.stationarysource.utils.ThrowableUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @ClassName ExecutionJob
 * @Description    此时任务是并发执行  有时候我们不需要任务并发执行
 *                 比如我们的任务要去"获取数据库中所有未发送邮件的名单"，如果是并发执行 就需要一个数据库锁去避免 数据被多次处理
 *                 这个时候就需要一个注解@DisallowConcurrentExecution
 * @Author 孙峰
 * @Date 2020/3/10 9:45
 * @Version 1.0
 */
@Async
// @DisallowConcurrentExecution  解决并发执行问题
public class ExecutionJob extends QuartzJobBean {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /** 该处仅供参考
     *  具体的线程配置根据具体硬件以及任务类型区分
     * */
    private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();

    @Override
    @SuppressWarnings("unchecked")
    protected void executeInternal(JobExecutionContext context) {
        QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
        // 获取spring bean
        QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean(QuartzLogRepository.class);
        QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class);

        QuartzLog log = new QuartzLog();
        log.setJobName(quartzJob.getJobName());
        log.setBeanName(quartzJob.getBeanName());
        log.setMethodName(quartzJob.getMethodName());
        log.setParams(quartzJob.getParams());
        long startTime = System.currentTimeMillis();
        log.setCronExpression(quartzJob.getCronExpression());
        try {
            // 执行任务
            logger.info("任务准备执行，任务名称：{}", quartzJob.getJobName());
            QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
                    quartzJob.getParams());
            Future<?> future = EXECUTOR.submit(task);
            future.get();
            long times = System.currentTimeMillis() - startTime;
            log.setTime(times);
            // 任务状态
            log.setSuccess(true);
            logger.info("任务执行完毕，任务名称：{} 总共耗时：{} 毫秒", quartzJob.getJobName(), times);
        } catch (Exception e) {
            logger.error("任务执行失败，任务名称：{}" + quartzJob.getJobName(), e);
            long times = System.currentTimeMillis() - startTime;
            log.setTime(times);
            // 任务状态 0：成功 1：失败
            log.setSuccess(false);
            log.setExceptionDetail(ThrowableUtil.getStackTrace(e));
            quartzJob.setPause(false);
            //更新状态
            quartzJobService.updateIsPause(quartzJob);
        } finally {
            quartzLogRepository.save(log);
        }
    }
}
